package service

import (
	"fmt"
	"gitee.com/filters/logger"
	"gitee.com/filters/starter/config"
	"gitee.com/filters/utils/conversion"
	"github.com/gin-gonic/gin"
	"github.com/robfig/cron/v3"
	"github.com/spf13/cast"
	"github.com/spf13/viper"
)

const (
	GinConfigKey = "Ginserver"
)

type GinServer struct {
	config     *viper.Viper
	engine     *gin.Engine
	httpConfig *config.GinConfig
}

func NewGin() *GinServer {
	s := &GinServer{}
	conf, err := config.LoadConfig(&config.ConfigMap{})
	if err != nil {
		panic(err)
	}
	s.SetEs(gin.Default())
	s.SetConfig(conf)
	return s
}

func (g *GinServer) SetGinConfig(es *config.GinConfig) {
	g.httpConfig = es
}

func (g *GinServer) GetGinConfig() *config.GinConfig {
	return g.httpConfig
}

func (g *GinServer) SetConfig(es *viper.Viper) {
	g.config = es
}

func (g *GinServer) GetConfig() *viper.Viper {
	return g.config
}

func (g *GinServer) SetEs(es *gin.Engine) {
	g.engine = es
}

func (g *GinServer) GetEs() *gin.Engine {
	return g.engine
}

// BindField 绑定数据
func (g *GinServer) BindField(f ...interface{}) *GinServer {
	for _, i2 := range f {
		conversion.ToStruct(g.GetConfig().AllSettings(), i2)
	}
	return g
}

// UseLog 日志记录
func (g *GinServer) UseLog() *GinServer {
	var logx config.GinLog
	if err := g.GetConfig().UnmarshalKey(logger.Logger, &logx); err != nil {
		panic(err)
	}
	logger.NewLog(logger.WithWritePath(logx.LogFilePath),
		logger.WithLogExt(logx.LogFileExt)).CurLog().WrapFormat()
	return g
}

// HandleMiddleware 绑定中间件
func (g *GinServer) HandleMiddleware(middles ...gin.HandlerFunc) *GinServer {
	g.GetEs().Use(middles...)
	return g
}

// HandleAddFunc 定时执行函数
func (g *GinServer) HandleAddFunc(list []*config.CronTabObj) *GinServer {
	c := cron.New(cron.WithSeconds())
	for index, crontabObj := range list {
		func(id int, obj *config.CronTabObj) {
			_, _ = c.AddJob(
				obj.CronTab, //一分钟
				cron.FuncJob(func() {
					_ = obj.Handler()
				}))
		}(index, crontabObj)
	}
	c.Start() //启动crond
	return g
}

// HandleRouter 绑定路由
func (g *GinServer) HandleRouter(route func(r *gin.Engine)) *GinServer {
	route(g.GetEs())
	return g
}

func (g *GinServer) Run() error {
	var ginx config.GinConfig
	if err := g.GetConfig().UnmarshalKey(GinConfigKey, &ginx); err != nil {
		panic(err)
	}
	g.SetGinConfig(&ginx)
	gin.SetMode(ginx.RunMode)
	fmt.Printf("http server:%s \n", fmt.Sprintf("http://127.0.0.1:%d", ginx.HttpPort))
	err := g.GetEs().Run(":" + cast.ToString(ginx.HttpPort))
	if err != nil {
		return err
	}
	return nil
}
